#include <QScreen>
#include <QGuiApplication>
#include <QFileDialog>
#include <QAxWidget>
#include <QAxObject>
#include <QMessageBox>
#include <QWindow>
#include <QDebug>

#include <QHBoxLayout>

#include <windows.h>

#include "qlsfunc.h"

QLsFunc::QLsFunc()
{

}

/* 将窗口移动到鼠标所在的显示屏，并居中显示 */
void QLsFunc::MoveWidgetToScreenWhereMouse(QWidget *w)
{
	/* 获取显示器列表 */
	QList<QScreen *> screenList = QGuiApplication::screens();
	foreach (QScreen *screen, screenList)
	{	/* 找到鼠标所在显示器 */
		if(screen->geometry().contains(QCursor::pos()))
		{
			/* 居中：screen->size().width() - width()) / 2
			 * 移动到鼠标所在显示器： + screen->geometry().x()
			 */
			w->move((screen->availableSize().width() - w->width()) / 2 + screen->geometry().x(),
				 (screen->availableSize().height() - w->height()) / 2 + screen->geometry().y());
		}
	}
}

/* 通过进程标题获取窗口进程ID */
QList<HWND> QLsFunc::GetWindowHandleListByPID(QString str_title)
{
	QList<HWND> HWND_list;
	HWND h = ::GetTopWindow(0);
	while (h)
	{
		DWORD pid = 0;
		DWORD dwTheardId = GetWindowThreadProcessId(h, &pid);

		if (dwTheardId != 0)
		{
			TCHAR *name = new TCHAR[MAX_PATH];
			::GetWindowTextW(h, name, 255);
			QString title = QString :: fromStdWString(name);
			if(title == str_title)
			{
				HWND_list.append(h);
			}
		}
		h = ::GetNextWindow(h, GW_HWNDNEXT);
	}
	return HWND_list;
}

/* 关闭WID的进程 */
void QLsFunc::CloseWindowHandleByWID(WId wid)
{
	if(wid)
	{
		DWORD dwId = 0;
		GetWindowThreadProcessId((HWND)wid, &dwId);
		HANDLE handle = OpenProcess(PROCESS_TERMINATE, 0, dwId);
		if(handle) TerminateProcess(handle, 0);
		CloseHandle(handle);
		wid = 0;
	}
}

/* 打开ppt并嵌入widget中 */
WId QLsFunc::OpenPptInsetWidget(QWidget *w, QString filePath/* = ""*/)
{	/* 文件路径校验，如果为空，则调用QFileDialog令用户选择想要打开的ppt */
	if(filePath.isEmpty())
	{
		filePath = QFileDialog::getOpenFileName(0, "Open ppt", QString(), "*.pptx *ppt;");
		if(filePath.isEmpty()) return 0;
	}

	/* 连接ppt控件 */
	QAxObject *ppt_dsoframer = new QAxObject(w);
	bool ppt_state = ppt_dsoframer->setControl("Powerpoint.Application");
	if(!ppt_state) QMessageBox::critical(w, "Error", "no office ppt！");
	/* 获取ppt信息 */
	QMap<QString,QVariant> mapProp = ppt_dsoframer->propertyBag();
	QString versionStr = mapProp.value("Version", "0").toString();
	int pptVersion = QString(versionStr.split(".").front()).toInt();

	/* 打开并放映ppt */
	ppt_dsoframer->dynamicCall("SetVisible(bool)", true);			/* 设置窗口显示 */
	ppt_dsoframer->querySubObject(
				"Presentations()")->dynamicCall(
				"Open(string)",
				QDir::toNativeSeparators(filePath));				/* 选择打开ppt的路径 */
	ppt_dsoframer->querySubObject(
				"ActivePresentation")->querySubObject(
				"SlideShowSettings")->dynamicCall("Run()");			/* 放映这个剪辑 */

	/* 将ppt嵌入QWidget *w */
	/* 获取文件名 */
	int index = filePath.lastIndexOf("/");
	QString filename = filePath.mid(index + 1, filePath.length());
	/* 根据ppt标题获取进程ID */
	QList<HWND> hwndList;
	if(pptVersion > 15)
	{	/* office version > 2010：2019兼容 */
		hwndList = GetWindowHandleListByPID(
					filename + " - PowerPoint");						/* 正常打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [兼容模式] - PowerPoint");			/* 兼容 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] - PowerPoint");				/* 只读 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] [兼容模式] - PowerPoint");		/* 只读 + 兼容 打开 */
	}
	else
	{	/* office version <= 2010：2010兼容 */
		hwndList = GetWindowHandleListByPID(
					filename + " - Microsoft PowerPoint");							/* 正常打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [兼容模式] - Microsoft PowerPoint");				/* 兼容 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] - Microsoft PowerPoint");				/* 只读 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] [兼容模式] - Microsoft PowerPoint");		/* 只读 + 兼容 打开 */
	}
	if(hwndList.size() == 0)
	{
		ppt_dsoframer->dynamicCall("Quit()");
		return 0;
	}
	/* 实例为QWidget并嵌入w */
	QWindow *pWin = QWindow::fromWinId((WId)hwndList.at(0));
	pWin->setGeometry(0, 0, w->width(), w->height());

	QWidget *widget = QWidget::createWindowContainer(pWin);
	widget->setMouseTracking(true);
	widget->setParent(w);

	QHBoxLayout *hLayout = nullptr;

	/**
	 * 如果原先有布局，则清空布局和子控件
	 *
	 * 由于这里无法知道上次QWindow的WId
	 * 所以外部线程的关闭就放在外面进行
	 * 这里只做Layout的清理
	 */
	if(w->layout())
	{
		QLayoutItem *item;
		while((item = w->layout()->takeAt(0)))
		{
			item->widget()->setParent(nullptr);
			delete item;
		}
		hLayout = qobject_cast<QHBoxLayout *>(w->layout());
	}
	else hLayout = new QHBoxLayout;

	hLayout->setMargin(0);
	hLayout->setSpacing(0);
	hLayout->addWidget(widget);

	w->setLayout(hLayout);

	return (WId)hwndList.at(0);
}

/* 打开word并嵌入widget中 */
WId QLsFunc::OpenWordInsetWidget(QWidget *w, QString filePath/* = ""*/)
{	/* 文件路径校验，如果为空，则调用QFileDialog令用户选择想要打开的word */
	if(filePath.isEmpty())
	{
		filePath = QFileDialog::getOpenFileName(0, "Open word", QString(), "*.doc *.docx;");
		if(filePath.isEmpty()) return 0;
	}

	/* 打开word */
	QAxWidget *word = new QAxWidget("Word.Application", 0, Qt::MSWindowsOwnDC);
	/* 获取word信息 */
	QMap<QString,QVariant> mapProp = word->propertyBag();
	qDebug() << mapProp;
	QString versionStr = mapProp.value("Version", "0").toString();
	int wordVersion = QString(versionStr.split(".").front()).toInt();
	word->setProperty("Visible", true);							/* 设置窗口显示 */
	QAxObject * documents = word->querySubObject("Documents");	/* 获取所有的工作文档 */
	documents->dynamicCall(
				"Open(QString)",
				QDir::toNativeSeparators(filePath));			/* 以文件template.doc为模版新建一个文档 */
	word->querySubObject("ActiveDocument");						/* 获取当前激活的文档 */

	/* 将word嵌入QWidget *w */
	/* 获取文件名 */
	int index = filePath.lastIndexOf("/");
	QString filename =filePath.mid(index+1,filePath.length());
	/* 根据word标题获取进程ID */
	QList<HWND> hwndList;
	if(wordVersion > 15)
	{	/* office version > 2010：2019兼容 */
		hwndList = GetWindowHandleListByPID(
					filename + " - Word");							/* 正常打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [兼容模式] - Word");				/* 兼容 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] - Word");				/* 只读 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] [兼容模式] - Word");		/* 只读 + 兼容 打开 */
	}
	else
	{	/* office version <= 2010：2010兼容 */
		hwndList = GetWindowHandleListByPID(
					filename + " - Microsoft Word");						/* 正常打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [兼容模式] - Microsoft Word");			/* 兼容 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] - Microsoft Word");				/* 只读 打开 */
		if(hwndList.size() == 0)
			hwndList = GetWindowHandleListByPID(
						filename + " [只读] [兼容模式] - Microsoft Word");		/* 只读 + 兼容 打开 */
	}
	if(hwndList.size() == 0)
	{
		word->dynamicCall("Quit()");
		return 0;
	}
	/* 实例为QWidget并嵌入w */
	QWindow *pWin = QWindow::fromWinId((WId)hwndList.at(0));
	pWin->setGeometry(0, 0, w->width(), w->height());

	QWidget *widget = QWidget::createWindowContainer(pWin);
	widget->setMouseTracking(true);//鼠标跟踪
	widget->setParent(w);

	QHBoxLayout *hLayout = nullptr;

	/**
	 * 如果原先有布局，则清空布局和子控件
	 *
	 * 由于这里无法知道上次QWindow的WId
	 * 所以外部线程的关闭就放在外面进行
	 * 这里只做Layout的清理
	 */
	if(w->layout())
	{
		QLayoutItem *item;
		while((item = w->layout()->takeAt(0)))
		{
			item->widget()->setParent(nullptr);
			delete item;
		}
		hLayout = qobject_cast<QHBoxLayout *>(w->layout());
	}
	else hLayout = new QHBoxLayout;

	hLayout->setMargin(0);
	hLayout->setSpacing(0);
	hLayout->addWidget(widget);
	w->setLayout(hLayout);

	return (WId)hwndList.at(0);
}
